package CI.aufgabe2.cip;


import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import CI.aufgabe2.cip.base.AbstractDescr;
import CI.aufgabe2.cip.descriptor.ProcedureDescr;
import CI.aufgabe2.cip.mynodes.MyFPSectionNode;
import CI.aufgabe2.cip.mynodes.MyIdNode;

public class SymbolTable  implements Serializable {
	
	/**
	 * 
	 */
	private static final long serialVersionUID = -3174521628703897282L;
	
	
	private Map<String, AbstractDescr>  descrMap = new HashMap<String, AbstractDescr>();
	private Map<String, Integer>  adressMap = new HashMap<String, Integer>();
	
	private int currAdr =0;
	private int currentParameterAddress = -3; //muss spaeter geaendert werden -> wenn SL-Register eingebaut
	private SymbolTable parentTable;
	
	
	public SymbolTable(){
		this.parentTable = null;
	}
	
	public SymbolTable parentTable(){
		return this.parentTable;
	}
	public int currentLvl(){
		if(this.parentTable == null) return 0;
		else return 1+parentTable.currentLvl();
	}
	public List<MyIdNode> getVarFormalParameters(){
		List<MyIdNode> idlist = new ArrayList<MyIdNode>();
		if(this.parentTable!=null)
			for(Entry<String, AbstractDescr> desc : this.parentTable.descrMap.entrySet())
				if(desc.getValue() instanceof ProcedureDescr)
					if(((ProcedureDescr)desc.getValue()).getParams()!=null)
						for(MyFPSectionNode fpnode : ((ProcedureDescr)desc.getValue()).getParams() )
							if(fpnode.getVarState())
								idlist.addAll(fpnode.getIdentList().getIdents());
		return idlist;
	}
	public int getLevelOf(String ident){
		int i;
		if(descrMap.containsKey(ident)){
			i=0;
		}else{
			i = 1 + parentTable.getLevelOf(ident);
		}
		return i;
	}
	
	public SymbolTable(SymbolTable table){
		this.parentTable = table;
	}
	public void declareParams(String ident, AbstractDescr descr){
			currentParameterAddress = currentParameterAddress - descr.getSize();
			adressMap.put(ident, currentParameterAddress);
			descrMap.put(ident, descr);
		
	}
	public void declare(String ident, AbstractDescr descr) {
		descrMap.put(ident, descr);
		adressMap.put(ident,currAdr);
		currAdr+=descr.getSize();
	}
	
	public int getSize(){
		return currAdr;
	}
	public AbstractDescr getDescr(String ident) {
		AbstractDescr descr = descrMap.get(ident);
		if(descr==null && parentTable != null)
			return parentTable.getDescr(ident);
		return descrMap.get(ident);
	}
	public Map<String, AbstractDescr> getDescrMap() {
		return descrMap;
	}
	public void setAdr(String ident,int newAdress){
		adressMap.put(ident, newAdress);
	}
	public int getAdr(String ident) {
		if(adressMap.containsKey(ident))
			return adressMap.get(ident);
		if(parentTable != null)
			return parentTable.getAdr(ident);
		return -1;
	}
	
	public String toString() {
		return descrMap.toString();
	}

}
